IOS开发 - 简单的计时器

项目介绍

4

项目完全由代码所写,没有使用storyboard,代码更具有复现性。

手动部分:需要将图片拖入assets

项目知识

SnapKit 布局

经典的Swift版的第三方库,专门用于项目的自动布局,目前在github上的stars就高达9340颗星。

作者仍然是写Objective-C的第三方库Masonry的大牛 - @Robert Payne

SnapKit配置

1.github下载:https://github.com/SnapKit/SnapKit

2.将下载下来的SnapKit项目的 SnapKit.xcodeproj 拖进自己的项目目录最外层中

3.工程文件 -> General -> Embedded Binaries 中点击加号,添加SnapKit库到项目中来

4.command+B 重新编译项目

SnapKit使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import UIKit
import SnapKit

class ViewController: UIViewController {
// 1.定义box
var box = UIView()

override func viewDidLoad() {
super.viewDidLoad()

box.backgroundColor = UIColor.orange
// 2.将box加入父视图,之后的布局是相对于父视图布局的
self.view.addSubview(box)
// 3. 添加布局的约束:上下左右、中心、
box.snp.makeConstraints { (make) -> Void in
make.width.equalTo(100)
make.height.equalTo(100)
make.center.equalTo(self.view)
}
}
}

Timer 计时器

初始化

1
2
3
4
self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true ,block:{ (timer) in
// withTimeInterval : 的值0.1s 时间片后,执行的代码
// repeats : withTimeInterval的时间后,是否继续重复
})

启动:fire

1
self.timer.fire()

您可以使用此方法来触发重复计时器,而不会中断其常规的触发计划。

如果计时器不重复 repeats,则在触发后自动失效,即使其预定的触发日期尚未到达。

暂停:invalidate(移除计时循环)

1
self.timer.invalidate()

官方的解释是:

This method is the only way to remove a timer from an NSRunLoop object. The NSRunLoop object removes and releases the timer, either just before the invalidate method returns or at some later point.

这是唯一一个把一个定时器从NSRunLoop object运行循环中移除的方法。

NSRunLoop object这个对象移除,并且release掉这个的定时器,或者是在这个invalidate方法返回的之前或是在之后的某个时间段,再进行移除并release操作。

guard

guard 打头只判断合理条件,保证判断条件简约

guard xxx : 如果不满足gurad后面的条件xxx,则执行else的内部代码

详见 guard详解

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//
// ViewController.swift
// WatchDemo
//
// Created by iris on 2019/2/27.
// Copyright © 2019 iris. All rights reserved.
//

// 学习:
import UIKit
import SnapKit

class ViewController: UIViewController {

var timer:Timer!
var resultLabel:UILabel! //计时器:文字显示
var resultNumber:Double = 0 //计时器:时间记录

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.

// 1.计时器的数字显示
// 1.1 数字的背景
let resultView = UIView()
resultView.backgroundColor = UIColor.init(red: 0.0, green: 0.0, blue: 0.1, alpha: 1)
// 注意:使用snp.makeConstraints方法的元素必须事先添加到父元素的中,例如:self.view.addSubview(view)
self.view.addSubview(resultView)
resultView.snp.makeConstraints{ (make) in
make.top.equalTo(0)
make.left.equalTo(0)
make.height.equalTo(300) // 长度 300
make.width.equalTo(self.view.frame.width)
}
// 1.2 数字的显示
resultLabel = UILabel()
self.view.addSubview(resultLabel)
resultLabel.textColor = UIColor.black
resultView.addSubview(resultLabel)
resultLabel.snp.makeConstraints{ (make) in
make.center.equalTo(resultView)
make.width.height.equalTo(140)
make.width.equalTo(400)
}
resultLabel.font = UIFont.init(name: "Helvetica Neue", size: 60)
resultLabel.text = "0.0"
resultLabel.textColor = UIColor .white
// 设置字体对齐方式
resultLabel.textAlignment = NSTextAlignment.center

// 2.开始按钮
// 2.1 开始按钮:背景
let startView = UIView()
startView.backgroundColor = UIColor.init(red: 0.1, green: 0.0, blue: 0.8, alpha: 0.8)
self.view.addSubview(startView)
startView.snp.makeConstraints { (make) in
make.top.equalTo(300)
make.left.equalTo(0)
make.bottom.equalTo(0)
make.width.equalTo(self.view.frame.width / 2)
}
// 2.2 开始按钮:布局
let startButton:UIButton = UIButton()
// startButton.setTitle("Start", for: UIControl.State.normal)
startButton.setImage(UIImage (imageLiteralResourceName: "start"), for: UIControl.State.normal)
startView.addSubview(startButton)
startButton.snp.makeConstraints { (make) in
make.center.equalTo(startView)
make.width.height.equalTo(50)
}
// 2.3 开始按钮:点击事件添加
startButton.addTarget(self, action: #selector(startHander), for: UIControl.Event.touchUpInside)

// 3 停止按钮
// 3.1 停止:背景
let stopView:UIView = UIView()
stopView.backgroundColor = UIColor.init(red: 0.1, green: 0.8, blue: 0.0, alpha: 0.8)
self.view.addSubview(stopView)
stopView.snp.makeConstraints { (make) in
make.top.equalTo(300)
make.bottom.equalTo(0)
make.right.equalTo(0)
make.width.equalTo(self.view.frame.width / 2)
}
// 3.2 停止:按钮
let stopButton:UIButton = UIButton()
// stopButton.setTitle("Stop", for: UIControl.State.normal)
stopButton.setImage(UIImage (imageLiteralResourceName: "pause"), for: UIControl.State.normal)
stopView.addSubview(stopButton)
stopButton.snp.makeConstraints { (make) in
make.center.equalTo(stopView)
make.width.height.equalTo(50)
}
// 3.2 停止:按钮事件添加
stopButton.addTarget(self, action: #selector(stopHander), for: UIControl.Event.touchUpInside)

// 4 重置
// 4.1 重置按钮
let resetButton:UIButton = UIButton()
resetButton.setTitle("Reset", for: UIControl.State.normal)
resetButton.titleLabel?.font = UIFont.init(name:"Helvetica Neue",size:20)
resultView.addSubview(resetButton)
resetButton.snp.makeConstraints { (make) in
make.right.equalTo(-10)
make.top.equalTo(10)
make.width.equalTo(100)
make.height.equalTo(50)
}
// 4.1 重置:事件监听
resetButton.addTarget(self, action: #selector(resetHander), for: UIControl.Event.touchUpInside)

}

// 3个按钮的事件函数
// 1.开始计时
@objc func startHander(){
if self.timer != nil{
self.stopHander()
}
self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true,block:{ (timer) in
self.resultNumber = self.resultNumber + 0.1
self.resultLabel.text = String(format:"%.1f",self.resultNumber)
})
self.timer.fire()
}
// 2.暂停时间
@objc func stopHander(){
// 2.1 不进行判断的方法,可能出现异常,内存可能泄露
// var timerForDistory:Timer!
// timerForDistory = self.timer
// timerForDistory.invalidate()

// 2.2 进行判断的方法,可能出现异常,内存可能泄露
// guard 打头只判断合理条件,保证判断条件简约
// guard xxx : 如果不满足gurad后面的条件xxx,则执行else的内部代码
guard let timerForDistory = self.timer else {
return
}
timerForDistory.invalidate()
}
// 3.重置计时器
@objc func resetHander(){
self.resultNumber = 0
self.resultLabel.text = "0.0"
}
}